<template>
	<div class="blogtoc-container">
		<h2>目录</h2>
		<RightList :list="tocWithSelect" @select="handleSelect" />
	</div>
</template>

<script>
import RightList from "./RightList.vue";
import eventBus from "@/eventBus";
import { debounce } from "@/utils";
export default {
	components: {
		RightList,
	},
	data() {
		return {
			activeAnchor: "",
		};
	},
	props: {
		toc: {
			type: Array,
		},
	},
	computed: {
		// 根据toc属性以及activeAnchor得到带有isSelect属性的toc数组
		tocWithSelect() {
			const getToc = (toc = []) => {
				return toc.map((t) => {
					return {
						...t,
						isSelected: t.anchor === this.activeAnchor,
						children: getToc(t.children),
					};
				});
			};
			return getToc(this.toc);
		},
		//根据toc获取dom
		doms() {
			const doms = [];
			const getDoms = (toc) => {
				for (const t of toc) {
					doms.push(document.getElementById(t.anchor));
					if (t.children && t.children.length) {
						getDoms(t.children);
					}
				}
			};
			getDoms(this.tocWithSelect);
			return doms;
		},
	},
	mounted() {
		this.setSelectDebounce = debounce(this.setSelect, 50);
		eventBus.$on("mainScroll", this.setSelectDebounce);
	},
	beforeDestroy() {
		eventBus.$off("mainScroll", this.setSelectDebounce);
	},
	methods: {
		//跳转到hash值位置
		handleSelect(item) {
			location.hash = item.anchor;
		},

		// 设置activeAnchor为正确的值
		setSelect(scrollDom) {
			//当前dom不存在则返回
			if (!scrollDom) {
				return;
			}
			// 由于后续要重新设置，先清空之前的状态
			this.activeAnchor = "";
			const range = 50; //范围
			for (const dom of this.doms) {
				// 看一下当前这个dom元素是不是应该被选中
				if (!dom) {
					continue;
				}
				// 得到元素离视口顶部的距离
				const top = dom.getBoundingClientRect().top;
				if (top > 0 && top < range) {
					//位于规定范围之内
					this.activeAnchor = dom.id;
				} else if (top > range) {
					//在规定范围下方
					return;
				} else {
					//在规定范围上方
					this.activeAnchor = dom.id; // 先假设自己是激活的，然后继续看后面
				}
			}
		},
	},
};
</script>

<style scoped lang="less">
h2 {
	font-size: 1em;
	font-weight: bold;
	margin: 0;
	letter-spacing: 2px;
}
</style>
